/**
 * @file controlbar.h
 * @brief
 *
 *
 *
 * @author 1823419256@qq.com
 * @version 1.0
 * @date 2011
*/

#ifndef MYBOOK_CTRLS_CONTROLBAR_H_
#define MYBOOK_CTRLS_CONTROLBAR_H_

#include "ctrls\imageservices.h"

const UINT WM_MYCONTROLBAR_NOTIFY = ::RegisterWindowMessage(_T("WM_MYCONTROLBAR_NOTIFY"));

class CMyControlBar
	: public CWindowImpl<CMyControlBar, CWindow, CControlWinTraits>
	, public CDoubleBufferImpl<CMyControlBar>
	, public CMouseHover<CMyControlBar>
{
public:
	DECLARE_WND_CLASS(_T("MyControlBar"))

	explicit CMyControlBar(CAspectAbstractFactory* pAspectFactory) 
		: m_pAspectFactory(pAspectFactory)
		, m_nSelectedTab(0)
		, m_nHoverTab(-1)
	{
		ATLASSERT(pAspectFactory);
		m_brBkgnd.CreateSolidBrush(m_pAspectFactory->GetBackColor());
	}

	void SetButtons(const std::vector<std::pair<int, CString>>& vecCmd, bool bRedraw = false)
	{
		m_vecCmd = vecCmd;

		if (bRedraw)
			Invalidate();
	}

	int GetCurCmdId() const
	{
		if (m_nSelectedTab >= 0 && m_nSelectedTab < (int)m_vecCmd.size())
		{
			return m_vecCmd[m_nSelectedTab].first;
		}

		return -1;
	}

public:
	BEGIN_MSG_MAP(CMyControlBar)
		CHAIN_MSG_MAP(CDoubleBufferImpl<CMyControlBar>)
		CHAIN_MSG_MAP(CMouseHover<CMyControlBar>)
		MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
		MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
		MESSAGE_HANDLER(WM_MOUSEENTER, OnMouseEnter)
		MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave)
		MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
	END_MSG_MAP()

// Handler prototypes (uncomment arguments if needed):
//	LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
//	LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
//	LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)

	void DoPaint(CDCHandle dc)
	{
		CClientRect rcClient(m_hWnd);
		
		// background
		dc.FillRect(rcClient, m_brBkgnd);

		// text
		dc.SetBkMode(TRANSPARENT);

		m_vecPos.resize(m_vecCmd.size());

		CRect rcDraw = rcClient;
		for (size_t i = 0; i < m_vecCmd.size(); ++i)
		{
			const CString& strText = m_vecCmd[i].second;

			CRect rcText;
			dc.SelectFont(m_pAspectFactory->GetTextBoldFont());
			dc.DrawText(strText, -1, &rcText, DT_CALCRECT);

			if (m_nSelectedTab == (int)i)
			{
				dc.SelectFont(m_pAspectFactory->GetTextBoldFont());
				dc.SetTextColor(m_pAspectFactory->GetTextSelectedColor());
			}
			else
			{
				dc.SelectFont(m_pAspectFactory->GetTextFont());

				if (m_nHoverTab == (int)i)
					dc.SetTextColor(m_pAspectFactory->GetTextHoverColor());
				else
					dc.SetTextColor(m_pAspectFactory->GetTextColor());
			}


			rcDraw.OffsetRect(12, 0);
			rcText.MoveToXY(rcDraw.TopLeft());
			rcText.bottom = rcDraw.bottom;

			dc.DrawText(strText, -1, rcText, DT_CENTER | DT_VCENTER | DT_SINGLELINE);

			if (m_nSelectedTab == (int)i || m_nHoverTab == (int)i)
			{
				CPen pen;

				if (m_nHoverTab == (int)i)
					pen.CreatePen(PS_DOT, 1, m_pAspectFactory->GetTextHoverColor());
				else
					pen.CreatePen(PS_DOT, 1, m_pAspectFactory->GetTextSelectedColor());

				dc.SelectPen(pen);
				dc.MoveTo(rcText.left, rcText.bottom - 3);
				dc.LineTo(rcText.right, rcText.bottom - 3);
			}

			m_vecPos[i] = rcText;
			rcDraw.OffsetRect(rcText.Width(), 0);
		}
	}

	LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
	{
		CPoint pt(lParam);

		int nSelectedTab = -1;
		for (size_t i = 0; i < m_vecPos.size(); ++i)
		{
			if (m_vecPos[i].PtInRect(pt))
			{
				nSelectedTab = i;
				break;
			}
		}

		if (nSelectedTab != -1 && m_nSelectedTab != nSelectedTab)
		{
			int nPrevSelect = m_nSelectedTab;
			m_nSelectedTab = nSelectedTab;

			InvalidateRect(m_vecPos[nSelectedTab], FALSE);
			if (nPrevSelect!= -1)
				InvalidateRect(m_vecPos[nPrevSelect], FALSE);

			::SendMessage(GetParent(), WM_MYCONTROLBAR_NOTIFY, m_vecCmd[m_nSelectedTab].first, (LPARAM)m_hWnd);
		}

		return 0;
	}

	LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
	{
		CPoint pt(lParam);

		int nHoverTab = -1;
		for (size_t i = 0; i < m_vecPos.size(); ++i)
		{
			if (m_vecPos[i].PtInRect(pt))
			{
				nHoverTab = i;
				break;
			}
		}

		if (m_nHoverTab != nHoverTab)
		{
			int nPrevHover = m_nHoverTab;
			m_nHoverTab = nHoverTab;

			if (nHoverTab != -1)
				InvalidateRect(m_vecPos[nHoverTab]);
			if (nPrevHover != -1)
				InvalidateRect(m_vecPos[nPrevHover]);
		}

		return 0;
	}

	LRESULT OnMouseEnter(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		return 0;
	}

	LRESULT OnMouseLeave(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		if (m_nHoverTab != -1)
		{
			int nPrevHover = m_nHoverTab;
			m_nHoverTab = -1;

			InvalidateRect(m_vecPos[nPrevHover], FALSE);
		}

		return 0;
	}

	LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
	{
		CPoint pt;
		GetCursorPos(&pt);
		ScreenToClient(&pt);

		bool bHandCursor = false;
		for (size_t i = 0; i < m_vecPos.size(); ++i)
		{
			if (m_vecPos[i].PtInRect(pt))
			{
				//SetCursor(m_handCursor);
				bHandCursor = true;
				break;
			}
		}

		bHandCursor ? SetCursor(LoadCursor(NULL, IDC_HAND)) 
					: SetCursor(LoadCursor(NULL,IDC_ARROW));

		return 0;
	}

protected:
	CBrush m_brBkgnd;

	int m_nSelectedTab;
	int m_nHoverTab;

	std::vector<std::pair<int, CString>> m_vecCmd;
	std::vector<CRect> m_vecPos;

protected:
	boost::scoped_ptr<CAspectAbstractFactory> m_pAspectFactory;
};

#endif // MYBOOK_CTRLS_CONTROLBAR_H_